package com.sscl.baselibrary.textwatcher

import androidx.annotation.*

import com.sscl.baselibrary.utils.DebugUtil
import android.text.TextWatcher
import android.text.Editable
import android.widget.EditText
import com.sscl.baselibrary.exts.formatToHex
import com.sscl.baselibrary.exts.isHexChar

/**
 * 自定义EditText输入过滤（限制只能输入十六进制字符，并且自动填充空格分割）
 *
 * @author alm
 */
open class HexTextAutoAddCharInputWatcher constructor(
    private val editText: EditText,
    maxInput: Int, @Size(1) character: Char
) : TextWatcher {

    /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
     *
     * 静态声明
     *
     * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

    companion object {

        /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
         *
         * 属性声明
         *
         * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

        /* * * * * * * * * * * * * * * * * * *  * * * * * * * * * * * * * * * * * * */

        private val TAG: String = HexTextAutoAddCharInputWatcher::class.java.simpleName
    }

    /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
     *
     * 属性声明
     *
     * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

    /* * * * * * * * * * * * * * * * * * * 常量属性 * * * * * * * * * * * * * * * * * * */

    private val maxInput: Int

    /**
     * the characters
     */
    private val character: Char

    /**
     * 每一个代表字节的字符串的长度
     */
    private val byteSize = 2

    /* * * * * * * * * * * * * * * * * * * 可变属性 * * * * * * * * * * * * * * * * * * */

    /**
     * 最终需要输入的文本
     */
    private var mLastText = ""

    /**
     * 正在编辑的文本
     */
    private var mEditing = ""

    private var clearing = false

    private var deleteMulti = false

    private var selection = 0

    /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
     *
     * 构造方法
     *
     * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

    init {
        this.maxInput = maxInput
        this.character = character
    }

    /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
     *
     * 实现方法
     *
     * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

    override fun beforeTextChanged(
        charSequence: CharSequence, start: Int,
        count: Int, after: Int
    ) {
        if (clearing) {
            return
        }
        val text = charSequence.toString().formatToHex(character)
        val split = text.split(character.toString())
        val endHex = if (split.isNotEmpty()) {
            split[split.size - 1]
        } else {
            text
        }
        if (text.isEmpty()) {
            selection = -1
            return
        }
        if (start > 0) {
            selection = if (count > 0) {
                start
            } else {
                val cache = start + after
                if (endHex.length == 2) {
                    //最后一个16进制字符长度为2，再新增字符时，会自动加一个[character]分割付，所以需要吧长度再+1
                    //不论中间如何增加或删除数据，最后一个字节长度都只可能是1 或者 2
                    cache + 1
                } else {
                    cache
                }
            }
        } else {
            if (count == 1) {
                selection = start + 1
            }
        }
        DebugUtil.warnOut(TAG, "selection $selection")
    }

    override fun onTextChanged(
        charSequence: CharSequence,
        start: Int,
        before: Int,
        count: Int
    ) {
        val mCurrentText = charSequence.toString()
        if (maxInput > 0) {
            val tempLength = mCurrentText.length
            val maxLength = if (mCurrentText.contains(character.toString())) {
                maxInput * (byteSize + 1) - 1
            } else {
                maxInput * byteSize
            }
            if (tempLength > maxLength) {
                DebugUtil.warnOut(TAG, "temp $tempLength > max $maxLength")
                return
            }
        }
        if (mCurrentText == mEditing) {
            return
        }

        if (count == 0) {
            if (clearing) {
                return
            }
            if (deleteMulti) {
                deleteMulti = false
                return
            }
            if (start - mCurrentText.length - 1 > 1) {
                deleteMulti = true
            }
            mEditing = mCurrentText.formatToHex(character)
            if (mCurrentText.isEmpty()) {
                mLastText = ""
            }
            return
        }
        val added = mCurrentText.substring(start, mCurrentText.length - before)
        var succeed = true
        for (addChar in added) {
            if (addChar == character) {
                continue
            }
            if (!addChar.isHexChar()) {
                succeed = false
                break
            }
        }
        if (!succeed) {
            mEditing = mLastText
            return
        }
        mEditing = mCurrentText.formatToHex(character)
    }

    override fun afterTextChanged(editable: Editable) {

        val text = editable.toString()
        if (text == mLastText) {
            clearing = false
            if (selection < 0) {
                selection = text.length
            } else if (selection > text.length) {
                selection = text.length
            }
            editText.setSelection(selection)
            return
        }
        if (text.isEmpty()) {
            editable.append(mLastText)
        } else {
            mLastText = mEditing
            clearing = true
            editable.clear()
        }
    }
}
